From 05c484dcb039aec955fd4592990704bea25fe7a7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Jan 2012 11:51:21 -0500 Subject: [PATCH] GtkApplication: add inhibitor dialog under OS X Since OS X doesn't have an inhibitors API, we need to display the inhibit reason ourselves. https://bugzilla.gnome.org/show_bug.cgi?id=667705 --- gtk/gtkapplication.c | 87 +++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c index 78c1b548e3..8a6a1db203 100644 --- a/gtk/gtkapplication.c +++ b/gtk/gtkapplication.c @@ -40,6 +40,7 @@ #include "gtkquartz-menu.h" #import #include +#include "gtkmessagedialog.h" #endif #include @@ -159,7 +160,7 @@ struct _GtkApplicationPrivate GActionMuxer *muxer; GMenu *combined; - GHashTable *inhibitors; + GSList *inhibitors; gint quit_inhibit; guint next_cookie; #endif @@ -255,6 +256,22 @@ gtk_application_shutdown_x11 (GtkApplication *application) #endif #ifdef GDK_WINDOWING_QUARTZ + +typedef struct { + guint cookie; + GtkApplicationInhibitFlags flags; + char *reason; + GtkWindow *window; +} GtkApplicationQuartzInhibitor; + +static void +gtk_application_quartz_inhibitor_free (GtkApplicationQuartzInhibitor *inhibitor) +{ + g_free (inhibitor->reason); + g_clear_object (&inhibitor->window); + g_slice_free (GtkApplicationQuartzInhibitor, inhibitor); +} + static void gtk_application_menu_changed_quartz (GObject *object, GParamSpec *pspec, @@ -295,7 +312,9 @@ gtk_application_shutdown_quartz (GtkApplication *application) g_object_unref (application->priv->muxer); application->priv->muxer = NULL; - g_hash_table_unref (application->priv->inhibitors); + g_slist_free_full (application->priv->inhibitors, + (GDestroyNotify) gtk_application_quartz_inhibitor_free); + application->priv->inhibitors = NULL; } static void @@ -1405,6 +1424,30 @@ idle_will_quit (gpointer data) if (app->priv->quit_inhibit == 0) g_signal_emit (app, gtk_application_signals[QUIT], 0); + else + { + GtkApplicationQuartzInhibitor *inhibitor; + GSList *iter; + GtkWidget *dialog; + + for (iter = app->priv->inhibitors; iter; iter = iter->next) + { + inhibitor = iter->data; + if (inhibitor->flags & GTK_APPLICATION_INHIBIT_LOGOUT) + break; + } + g_assert (inhibitor != NULL); + + dialog = gtk_message_dialog_new (inhibitor->window, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("%s cannot quit at this time:\n\n%s"), + g_get_application_name (), + inhibitor->reason); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } return FALSE; } @@ -1431,8 +1474,6 @@ gtk_application_startup_session_quartz (GtkApplication *app) AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP (quit_requested), (long)GPOINTER_TO_SIZE (app), false); - - app->priv->inhibitors = g_hash_table_new (NULL, NULL); } guint @@ -1441,42 +1482,46 @@ gtk_application_inhibit (GtkApplication *application, GtkApplicationInhibitFlags flags, const gchar *reason) { - guint cookie; + GtkApplicationQuartzInhibitor *inhibitor; g_return_val_if_fail (GTK_IS_APPLICATION (application), 0); g_return_val_if_fail (flags != 0, 0); - application->priv->next_cookie++; - cookie = application->priv->next_cookie; + inhibitor = g_slice_new (GtkApplicationQuartzInhibitor); + inhibitor->cookie = ++application->priv->next_cookie; + inhibitor->flags = flags; + inhibitor->reason = g_strdup (reason); + inhibitor->window = window ? g_object_ref (window) : NULL; - g_hash_table_insert (application->priv->inhibitors, - GUINT_TO_POINTER (cookie), - GUINT_TO_POINTER (flags)); + application->priv->inhibitors = g_slist_prepend (application->priv->inhibitors, inhibitor); if (flags & GTK_APPLICATION_INHIBIT_LOGOUT) application->priv->quit_inhibit++; - return cookie; + return inhibitor->cookie; } void gtk_application_uninhibit (GtkApplication *application, guint cookie) { - GtkApplicationInhibitFlags flags; - - flags = GPOINTER_TO_UINT (g_hash_table_lookup (application->priv->inhibitors, GUINT_TO_POINTER (cookie))); + GSList *iter; - if (flags == 0) + for (iter = application->priv->inhibitors; iter; iter = iter->next) { - g_warning ("Invalid inhibitor cookie"); - return; + GtkApplicationQuartzInhibitor *inhibitor = iter->data; + + if (inhibitor->cookie == cookie) + { + if (inhibitor->flags & GTK_APPLICATION_INHIBIT_LOGOUT) + application->priv->quit_inhibit--; + gtk_application_quartz_inhibitor_free (inhibitor); + application->priv->inhibitors = g_slist_delete_link (application->priv->inhibitors, iter); + return; + } } - g_hash_table_remove (application->priv->inhibitors, GUINT_TO_POINTER (cookie)); - - if (flags & GTK_APPLICATION_INHIBIT_LOGOUT) - application->priv->quit_inhibit--; + g_warning ("Invalid inhibitor cookie"); } gboolean -- 2.30.2